﻿using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using App.Common;
using QxFramework.Core;
using System;
public class MonoManager : LogicModuleBase, IMonoManager
{
    public AllMono allMono;
    public override void Init()
    {
        base.Init();
        if (!RegisterData(out allMono))
        {
            InitAllData();
        }
    }
    private void InitAllData()
    {
        allMono = new AllMono();
    }
    public override void FixedUpdate()
    {
        base.FixedUpdate();
        UpdateAllMono();
    }

    /// <summary>
    /// 同步场上所有Mono
    /// </summary>
    public void UpdateAllMono()
    {
        foreach (string key in allMono._ObjList.Keys)
        {
            if (!allMono._MonoList.ContainsKey(key))
            {
                RemoveObj(key);
                break;
            }
        }
        foreach (string key in allMono._MonoList.Keys)
        {
            if (allMono._ObjList.ContainsKey(key))
            {
                if (allMono._ObjList[key] == null)
                {
                    allMono._ObjList.Remove(key);
                    continue;
                }
            }
            else
            {
                AddObj(key,out GameObject Clone);
            }
            allMono._ObjList[key].transform.position = allMono._MonoList[key].Position;
            GameMgr.Get<ICameraManager>().UpdateCamera();
            HpJudge(allMono._MonoList[key]);
            LpJudge(allMono._MonoList[key]);
            TipsJudge(allMono._MonoList[key]);
            LostingJudge(allMono._MonoList[key]);
            for (int i=0; i< allMono._MonoList[key].SkillList.Count; i++)
            {
                MpJudge(allMono._MonoList[key], allMono._MonoList[key].SkillList[i]);
                GameMgr.Get<ISkillManager>().CountCD(allMono._MonoList[key].SkillList[i]);
            }
        }
    }
    public Mono GetMono(string name)
    {
        if (!allMono._MonoList.ContainsKey(name))
        {
            return new Mono();
        }
        return allMono._MonoList[name];
    }
    public GameObject GetObj(Mono mono)
    {
        foreach(string key in allMono._MonoList.Keys)
        {
            if(allMono._MonoList[key] == mono)
            {
                return allMono._ObjList[key];
            }
        }
        return null;
    }
    public AllMono GetAllMono()
    {
        return allMono;
    }

    #region Mono相关函数

    /// <summary>
    /// 清除所有Mono
    /// </summary>
    /// <param name="mono"></param>
    public void ClearAll(MonoBase.MonoTag tag)
    {
        if(tag == MonoBase.MonoTag.All)
        {
            allMono._MonoList = new Dictionary<string, Mono>();
        }
        foreach (string key in allMono._ObjList.Keys)
        {
            if(allMono._ObjList[key].tag == tag.ToString())
            {
                allMono._MonoList.Remove(key);
            }
        }
    }

    /// <summary>
    /// 添加一个对象
    /// </summary>
    /// <param name="mono"></param>
    public void AddMono(string Name, Mono mono)
    {
        string NameTemp = Name + "_0";
        int IDtemp = 0;
        while (allMono._MonoList.ContainsKey(NameTemp))
        {
            IDtemp++;
            NameTemp = Name + "_" + IDtemp;
        }
        allMono._MonoList.Add(NameTemp, mono);
    }
    private void AddObj(string Name, out GameObject Clone)
    {
        GameObject clone = ResourceManager.Instance.Instantiate("Prefabs/CreatedMono/" + Name.Split('_')[0], GameObject.Find("SceneObjs").transform);
        clone.name = Name;
        clone.transform.position = allMono._MonoList[Name].Position;
        GameObject effect = ResourceManager.Instance.Instantiate("Prefabs/Effects/MonoAppear", GameObject.Find("SceneObjs").transform);
        effect.transform.position = clone.transform.position;
        Clone = clone;
        allMono._ObjList.Add(Name, clone);
    }
    /// <summary>
    /// 移除一个对象
    /// </summary>
    /// <param name="mono"></param>
    public void RemoveMono(string Name)
    {
        if (!allMono._MonoList.ContainsKey(Name))
        {
            Debug.LogError("MonoList没有" + Name);
            return;
        }
        allMono._MonoList.Remove(Name);
    }
    private void RemoveObj(string Name)
    {
        GameObject clone = allMono._ObjList[Name];
        allMono._ObjList.Remove(Name);
        ResourceManager.Instance.Destroy(clone);
    }

    /// <summary>
    /// 移动一个对象
    /// </summary>
    /// <param name="mono"></param>
    public void MoveMono(Mono mono, Vector3 Direction, float Speed)
    {
        Vector3 Direc = new Vector3(Direction.x, Direction.y, 0);
        mono.Position += Direc.normalized * Speed;
    }

    /// <summary>
    /// 更改属性
    /// </summary>
    /// <param name="mono"></param>
    public void ChangeAttr(Mono mono, MonoAttribute attr)
    {
        mono.Attr = attr;
    }
    #endregion

    #region HP相关函数

    /// <summary>
    /// HP值加减
    /// </summary>
    /// <param name="mono"></param>
    public void ChangeHPValue(Mono mono, int hp)
    {
        if(hp == 0)
        {
            return;
        }
        JumpText(mono.Position, ((hp < 0) ? "" : "+") + hp.ToString(), (hp > 0) ? Color.green : Color.white);
        mono.HPData.HPValue += hp;
    }
    /// <summary>
    /// 跳出文本
    /// </summary>
    /// <param name="mono"></param>
    public void JumpText(Vector3 Pos, string text, Color color)
    {
        GameObject clone = ResourceManager.Instance.Instantiate("Prefabs/Others/DamageText");
        clone.transform.position = Pos;
        clone.GetComponentInChildren<TextMesh>().text = text;
        clone.GetComponentInChildren<TextMesh>().color = color;
    }
    /// <summary>
    /// 跳出文本
    /// </summary>
    /// <param name="mono"></param>
    public void JumpText(Mono mono, string text, int colorID)
    {
        GameObject clone = ResourceManager.Instance.Instantiate("Prefabs/Others/DamageText");
        clone.transform.position = mono.Position;
        clone.GetComponentInChildren<TextMesh>().text = text;
        clone.GetComponentInChildren<TextMesh>().color = Data.Instance.PrintColor[colorID];
    }

    private void HpJudge(Mono mono)
    {
        if (mono.HPData.HPValue > mono.HPData.HPCeiling)
        {
            mono.HPData.HPValue = mono.HPData.HPCeiling;
        }
        if (mono.HPData.HPValue < 0)
        {
            mono.HPData.HPValue = 0;
            if(GameMgr.Get<IBattleManager>().GetBattleData().monos[GameMgr.Get<IBattleManager>().GetBattleData().CurrentID] == GameMgr.Get<IMonoManager>().GetObj(mono).name)
            {
                GameMgr.Get<IBattleManager>().EndThisTurn();
            }
            Die(GetObj(mono));
        }
    }
    private void Die(GameObject obj)
    {
        GetMono(obj.name).monoRealtimeStatus.IsDying = true;
        obj.GetComponentInChildren<AnimationUtil>().SetTrigger("Die", () => {
            if (allMono._MonoList.ContainsKey(obj.name))
            {
                RemoveMono(obj.name);
            }
        });
    }


    /// <summary>
    /// HP上限加减
    /// </summary>
    /// <param name="mono"></param>
    public void ChangeHPCeiling(Mono mono,int hp)
    {
        mono.HPData.HPCeiling += hp;
    }
    private void MpJudge(Mono mono,SkillBase skillBase)
    {
        if (mono.MPData.MPValue > mono.MPData.MPCeiling)
        {
            mono.MPData.MPValue = mono.MPData.MPCeiling;
        }
        if (mono.MPData.MPValue < 0)
        {
            mono.MPData.MPValue = 0;
        }
        //CD期间不回复MP
        for (int i = 0; i < mono.SkillList.Count; i++)
        {
            if (mono.SkillList[i].CD.CurrentCD > 0)
            {
                return;
            }
        }
        if (!GameMgr.Get<IBattleManager>().GetBattleData().InBattle)
        {
            mono.MPData.MPValue += mono.MPData.RecoverSpeed;
        }
    }
    private void LpJudge(Mono mono)
    {
        if (mono.LPData.LPValue > mono.LPData.LPCeiling)
        {
            mono.LPData.LPValue = mono.LPData.LPCeiling;
        }
        if (mono.LPData.LPValue < 0)
        {
            mono.LPData.LPValue = 0;
        }
        if (!GameMgr.Get<IBattleManager>().GetBattleData().InBattle)
        {
            mono.LPData.LPValue += mono.LPData.RecoverSpeed;
        }
    }
    private void TipsJudge(Mono mono)
    {
        if (mono.monoRealtimeStatus.AttackTips)
        {
            if (mono.AttackTipsData.CurrentValue <= 0)
            {
                mono.AttackTipsData.CurrentValue = 0;
            }
            else
            {
                if (GameMgr.Get<IBattleManager>().GetCurrentBattleMono() == mono)
                {
                    mono.AttackTipsData.CurrentValue -= Time.deltaTime;
                }
            }
        }
    }

    /// <summary>
    /// 临时HP加减
    /// </summary>
    /// <param name="mono"></param>
    public void ChangeTempHPValue(Mono mono, int hp, TempHP type)
    {
        mono.HPData.TempValue[type] += hp;
    }

    /// <summary>
    /// 范围判断
    /// </summary>
    /// <param name="mono"></param>
    public bool WithInRage(Mono mono, Vector3 Pos, MonoBase.MonoTag tag, float range, out bool LostTarget, out Vector3 Direction, out GameObject Obj)
    {
        LostTarget = true;
        if (GameObject.FindGameObjectsWithTag(tag.ToString()) == null)
        {
            Direction = Vector3.zero;
            Obj = null;
            return false;
        }
        GameObject[] AllObj = GameObject.FindGameObjectsWithTag(tag.ToString());
        Direction = Vector3.zero;
        Obj = null;
        float rangetemp = Mathf.Infinity;
        foreach (GameObject obj in AllObj)
        {
            if(obj == GetObj(mono))
            {
                continue;
            }
            float rangetemp2 = (obj.transform.position - Pos).magnitude;
            if (rangetemp2 < rangetemp)
            {
                Direction = (obj.transform.position - Pos);
                Obj = obj;
                rangetemp = rangetemp2;
            }
            LostTarget = false;
        }
        return rangetemp < range;
    }
    public Vector3 GetNearestMonoPos(Mono mono, MonoBase.MonoTag tag)
    {
        GameObject[] AllObj = GameObject.FindGameObjectsWithTag(tag.ToString());
        Vector3 target = new Vector3();
        float dis = float.MaxValue;
        foreach (GameObject obj in AllObj)
        {
            float temp = GetDistance(obj.transform.position, mono.Position);
            if (GetMono(obj.name) == mono)
            {
                continue;
            }
                if (dis > temp)
            {
                target = obj.transform.position;
                dis = temp;
            }
        }
        return target;
    }
    private float GetDistance(Vector3 pos1, Vector3 pos2)
    {
        return Mathf.Sqrt((pos1.x - pos2.x) * (pos1.x - pos2.x) + (pos1.y - pos2.y) * (pos1.y - pos2.y));
    }
    #endregion

    #region MP相关函数

    /// <summary>
    /// MP加减
    /// </summary>
    /// <param name="mono"></param>
    public void ChangeMPValue(Mono mono,SkillBase skillBase,int mp)
    {
        mono.MPData.MPValue += mp;
    }

    /// <summary>
    /// MP上限加减
    /// </summary>
    /// <param name="mono"></param>
    public void ChangeMPCeiling(Mono mono, int mp)
    {
        mono.MPData.MPCeiling += mp;
    }

    /// <summary>
    /// MP回复速度加减
    /// </summary>
    /// <param name="mono"></param>
    public void ChangeMPSpeed(Mono mono, int speed)
    {
        mono.MPData.RecoverSpeed += speed;
    }

    /// <summary>
    /// MP加减
    /// </summary>
    /// <param name="mono"></param>
    public void ChangeLPValue(Mono mono, int lp)
    {
        mono.LPData.LPValue += lp;
    }

    /// <summary>
    /// 当前属性的名称
    /// </summary>
    /// <param name="mono"></param>
    public string CurrentAttrName(MonoAttribute Attr)
    {
        switch (Attr)
        {
            case MonoAttribute.None:
                return "Default";
            case MonoAttribute.Fire:
                return "Fire";
            case MonoAttribute.Ice:
                return "Ice";
            case MonoAttribute.Shine:
                return "Shine";
            case MonoAttribute.Dark:
                return "Dark";
            case MonoAttribute.Steam:
                return "Steam";
            case MonoAttribute.Electric:
                return "Electric";
            case MonoAttribute.Oil:
                return "Oil";
            default:
                return "";
        }
    }

    private void LostingJudge(Mono mono)
    {
        if(mono.monoRealtimeStatus.LostingRate < 0)
        {
            mono.monoRealtimeStatus.LostingRate = 0;
        }
        mono.monoRealtimeStatus.LostingRate -= Time.deltaTime;
    }

    #endregion

    public void Cheat()
    {
        foreach (string key in allMono._MonoList.Keys)
        {
            if (!key.Contains("Player"))
            {
                allMono._MonoList.Remove(key);
                return;
            }
        }
    }
}

public enum MonoAttribute
{
    None,
    Fire,
    Ice,
    Dark,
    Shine,
    Steam,
    Electric,
    Oil
}
public enum TempHP
{
    Normal,
    Shield
}
public class HP
{
    /// <summary>
    /// 血量数值
    /// </summary>
    public int HPValue =0;

    /// <summary>
    /// 血量上限
    /// </summary>
    public int HPCeiling =0;

    /// <summary>
    /// 回复速度
    /// </summary>
    public int RecoverSpeed = 0;

    /// <summary>
    /// 临时血量<类型，数值>
    /// </summary>
    public Dictionary<TempHP, int> TempValue = new Dictionary<TempHP, int>();
}
public class MP
{
    /// <summary>
    /// 魔力上限
    /// </summary>
    public int MPCeiling = 0;

    /// <summary>
    /// 魔力值
    /// </summary>
    public int MPValue = 0;

    /// <summary>
    /// 回复速度
    /// </summary>
    public int RecoverSpeed = 0;
}
public class LP
{
    /// <summary>
    /// 体力上限
    /// </summary>
    public int LPCeiling = 0;

    /// <summary>
    /// 当前
    /// </summary>
    public int LPValue = 0;

    /// <summary>
    /// 回复速度
    /// </summary>
    public int RecoverSpeed = 0;
}
public class AttackTips
{
    /// <summary>
    /// 时间上限
    /// </summary>
    public float ValueCeiling = 0;

    /// <summary>
    /// 当前数值
    /// </summary>
    public float CurrentValue = 0;

}

[Serializable]
public class Mono
{
    /// <summary>
    /// 血量数据
    /// </summary>
    public HP HPData=new HP();

    /// <summary>
    /// 蓝数据
    /// </summary>
    public MP MPData = new MP();

    /// 体力数据
    /// </summary>
    public LP LPData = new LP();

    /// 攻击前摇
    /// </summary>
    public AttackTips AttackTipsData = new AttackTips();

    /// <summary>
    /// 速度
    /// </summary>
    public float Speed =0;

    /// <summary>
    /// 射程
    /// </summary>
    public float Range =0;

    /// <summary>
    /// 当前坐标
    /// </summary>
    public Vector3 Position = Vector3.zero;

    /// <summary>
    /// 当前朝向
    /// </summary>
    public Vector3 Direction = Vector3.zero;

    /// <summary>
    /// 属性
    /// </summary>
    public MonoAttribute Attr = new MonoAttribute();

    /// <summary>
    /// 道具
    /// </summary>
    public Dictionary<int, int> Props = new Dictionary<int, int>();

    /// <summary>
    /// 技能列表
    /// </summary>
    public List<SkillBase> SkillList = new List<SkillBase>();

    /// <summary>
    /// 技能列表
    /// </summary>
    public List<int> ItemList = new List<int>();

    /// <summary>
    /// Buff列表
    /// </summary>
    public Dictionary<int,Buff> BuffList = new Dictionary<int, Buff>();

    /// <summary>
    /// 实时属性
    /// </summary>
    public MonoRealtimeStatus monoRealtimeStatus = new MonoRealtimeStatus();

    /// <summary>
    /// buff属性
    /// </summary>
    public BuffStatus buffStatus = new BuffStatus();

}

public class MonoRealtimeStatus
{
    public float LostingRate = 0;
    public bool IsInvincible = false;
    public bool IsCounterAttack = false;
    public bool IsDying = false;
    public bool IsCDing = false;
    public bool AttackTips = false;
    public bool IsElectriciting = false;
    public bool IsSteamed = false;
    public float IsFrozen = 0;
}
public class BuffStatus
{
    public int DefaultAttckAdd = 0;
    public int AddAtrrNum = 0;
    public float BuffAttrLastTime = 0;
    public int AttrLastTime = Data.Instance.TableAgent.GetInt("Base", "AttrLastTime", "Value");
}
public class AllMono : GameDataBase
{
    /// <summary>
    /// 场上的所有Mono
    /// </summary>
    public Dictionary<string, Mono> _MonoList = new Dictionary<string, Mono>();
    /// <summary>
    /// 场上的所有Mono的Gameobj
    /// </summary>
    public Dictionary<string, GameObject> _ObjList = new Dictionary<string, GameObject>();

}
